package com.siruier.boss.ui.api

import android.content.Context
import android.widget.TextView
import androidx.lifecycle.Observer
import com.kingja.loadsir.core.LoadService
import com.scwang.smart.refresh.layout.api.RefreshLayout
import com.siruier.boss.api.core.ApiProcess
import com.siruier.boss.api.core.FirmException
import com.siruier.boss.api.core.NotNetworkException
import com.siruier.boss.api.core.ResultBean
import com.siruier.boss.api.core.enums.ApiCode
import com.siruier.boss.router.ROUTER_LOGIN
import com.siruier.boss.router.startRouter
import com.siruier.boss.ui.AppCore
import com.siruier.boss.ui.R
import com.siruier.boss.ui.dialog.LoadingDialog
import com.siruier.boss.ui.ext.showLoadingBeforeSuccessCallback
import com.siruier.boss.ui.ext.toastMessageLong
import com.siruier.boss.ui.helper.loadsir.ErrorCallback
import com.siruier.boss.ui.helper.loadsir.NotNetworkCallback
import com.siruier.boss.ui.listener.OnValidationResultListener
import com.siruier.boss.ui.listener.RefreshListener
import com.siruier.boss.ui.listener.SmartRefreshListener
import com.siruier.boss.ui.utils.Logger
import com.tencent.bugly.crashreport.CrashReport
import java.io.IOException
import java.net.SocketException


/**
 * 接口请求处理类
 */
open class ApiObserver<T>(
    private var context: Context? = null,
    private var dialog: LoadingDialog? = null,
    private var cancelable: Boolean = true,
    private var showMsg: Boolean = true,
    private var showLoadingDialog: Boolean = true,
    private var commonButton: OnValidationResultListener? = null,
    private var loadService: LoadService<*>? = null,
    refreshLayout: RefreshLayout? = null,
    private var apiObserver: ApiObserver<T>? = null,
    private var complete: (() -> Unit)? = null,
    private var error: ((e: Throwable?) -> Unit)? = null,
    var success: ((T?) -> Unit)? = null,
) : Observer<ApiProcess<T>> {
    private var refreshListener: RefreshListener? = null

    init {
        if (refreshLayout != null) refreshListener = SmartRefreshListener(refreshLayout)
    }

    override fun onChanged(apiProcess: ApiProcess<T>) {
        when (apiProcess.apiCode) {
            ApiCode.START -> start()
            ApiCode.SUCCESS -> success(apiProcess.data)
            ApiCode.ERROR -> onError(apiProcess.throwable)
            ApiCode.COMPLETE -> onComplete()
        }
    }

    open fun start() {
        apiObserver?.start()
        if (loadService != null) {
            loadService?.showLoadingBeforeSuccessCallback()
        } else {
            try {
                if (dialog == null && context != null && showLoadingDialog) {
                    dialog = LoadingDialog(context!!)
                    dialog?.setCancelable(cancelable)
                }
                com.siruier.boss.ui.utils.SafeDialogHandle.safeShowDialog(dialog)
            } catch (e: Exception) {
                Logger.e(e)
            }
        }
        commonButton?.enable(false)
    }

    open fun success(t: T?) {
        try {
            loadService?.showSuccess()
            dismiss()
            success?.invoke(t)
            apiObserver?.success(t)
        } catch (e: Exception) {
            onError(e)
        }
    }

    open fun onError(e: Throwable?) {
        apiObserver?.onError(e)
        refreshListener?.stopRefresh()
        try {
            error?.invoke(e)
            if (showMsg) {
                if (e is FirmException) {
                    if (!doFirmError(e) && !e.message.isNullOrEmpty()) {
                        toastMessageLong(if (e.message!!.length > 100) " 服务器异常" else e.message)
                    }
                } else if (e is IOException || e is SocketException) {
                    toastMessageLong("网络连接失败")
                } else if ("kotlinx.coroutines.JobCancellationException" == e?.javaClass?.name) {
                    //toastMessageLong("网络连接失败")
                } else {
                    toastMessageLong("加载未成功")
                }
            }
            var errorMessage: String? = null
            if (e is FirmException) {
                errorMessage = e.message
                Logger.e("e==>")
                if (ResultBean.NOT_LOGIN == e.code) {
                    kotlin.runCatching {
                        (context ?: AppCore.app).startRouter(ROUTER_LOGIN)
                    }
                }
            } else {
                CrashReport.postCatchedException(e)
            }
            Logger.e(e)
            doError(e)
            if (loadService != null) {
                if (e is NotNetworkException) {
                    loadService?.showCallback(NotNetworkCallback::class.java)
                } else {
//                    if (errorMessage != null) {
                    loadService?.setCallBack(ErrorCallback::class.java) { context, view ->
                        view.findViewById<TextView>(R.id.tv_text).text = e?.message ?: ""
                    }
//                    }
//                    loadService?.showCallback(ErrorCallback::class.java)
                }
            }
        } catch (e1: Exception) {
            Logger.e(e1)
        }
        dismiss()
    }

    open fun onComplete() {
        apiObserver?.onComplete()
        complete?.invoke()
        refreshListener?.stopRefresh()
        commonButton?.enable(true)
        onDestroy()
    }

    /**
     * @return 业务异常是否已被处理
     */
    open fun doFirmError(e: FirmException): Boolean {
        return false
    }

    /**
     * 子类自己处理异常
     */
    open fun doError(e: Throwable?) {}

    fun onDismiss() {}

    fun dismiss() {
        com.siruier.boss.ui.utils.SafeDialogHandle.safeDismissDialog(dialog)
        onDismiss()
    }

    fun onDestroy() {
        dismiss()
        success = null
        context = null
        dialog = null
        loadService = null
        refreshListener = null
        commonButton = null
    }
}